<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>轮播图组件示例--3</title>
    <style>
        .carousel {
            width: 80%;
            margin: auto;
            overflow: hidden;
            position: relative;
        }
        .carousel-inner {
            display: flex;
            transition: transform 0.5s ease-in-out; /* 平滑过渡效果 */
        }
        .carousel-item {
            min-width: 100%;
            box-sizing: border-box;
        }
        .carousel-item img {
            width: 100%;
            height: auto; /* 保持图片的宽高比 */
            display: block;
        }
        .carousel-control {
            position: absolute;
            top: 50%;
            transform: translateY(-50%);
            background: rgba(0, 0, 0, 0.5);
            color: white;
            border: none;
            padding: 10px;
            cursor: pointer;
        }
        .carousel-control.prev {
            left: 10px;
        }
        .carousel-control.next {
            right: 10px;
        }
    </style>
</head>
<body>

<!-- 轮播图容器 -->
<div id="carousel1"></div>

<script>
    // 轮播图组件类
    class Carousel {
        /**
         * Carousel 类的构造函数，用于初始化轮播图实例。
         * @param {HTMLElement} container - 轮播图要挂载的 DOM 容器元素。
         * @param {Object} config - 轮播图的配置对象。
         * @param {Array<string>} [config.imageNames=[]] - 包含轮播图图片文件名的数组。
         * @param {string} [config.imageBasePath=''] - 轮播图图片所在的基础路径。这边只添加路径后面的路径分隔符，下面程序代码中会添加
         * @param {number} [config.autoPlayInterval=3000] - 轮播图自动播放的时间间隔，单位为毫秒。
         * @param {string} [config.transitionType='slide'] - 轮播图切换效果类型，可选值为 'slide'（滑动）或 'fade'（淡入淡出）。
         */
        constructor(container, config) {
            this.container = container; // 轮播图容器
            this.config = {
                imageNames: config.imageNames || [], // 图片名称数组
                imageBasePath: config.imageBasePath || '', // 图片基础路径
                autoPlayInterval: config.autoPlayInterval || 3000, // 自动播放间隔
                transitionType: config.transitionType || 'slide', // 切换方式：slide（滑动）或 fade（淡入淡出）
            };
            this.currentIndex = 0; // 当前显示的图片索引
            this.totalItems = this.config.imageNames.length; // 图片总数
            this.init(); // 初始化轮播图
        }

        // 初始化轮播图
        init() {
            this.container.innerHTML = `
                <div class="carousel">
                    <div class="carousel-inner"></div>
                    <button class="carousel-control prev">&#10094;</button>
                    <button class="carousel-control next">&#10095;</button>
                </div>
            `;

            this.carouselInner = this.container.querySelector('.carousel-inner');
            this.prevButton = this.container.querySelector('.carousel-control.prev');
            this.nextButton = this.container.querySelector('.carousel-control.next');

            this.createImages(); // 创建图片
            this.bindEvents(); // 绑定事件
            this.startAutoPlay(); // 启动自动播放
        }

        // 创建图片
        createImages() {
            // 克隆最后一张图片并添加到开头
            const lastItemClone = this.carouselInner.lastElementChild?.cloneNode(true) || document.createElement('div');
            this.carouselInner.insertBefore(lastItemClone, this.carouselInner.firstElementChild);

            this.config.imageNames.forEach((imageName, index) => {
                const item = document.createElement('div');
                item.classList.add('carousel-item');
                const img = document.createElement('img');
                img.src = `${this.config.imageBasePath}/${imageName}`;
                img.alt = `Slide ${index + 1}`;
                item.appendChild(img);
                this.carouselInner.appendChild(item);
            });

            // 克隆第一张图片并添加到末尾
            const firstItemClone = this.carouselInner.firstElementChild.cloneNode(true);
            this.carouselInner.appendChild(firstItemClone);
        }

        // 显示指定索引的图片
        showSlide(index) {
            if (index < 0) {
                this.currentIndex = this.totalItems - 1;
                this.carouselInner.style.transition = 'none';
                this.carouselInner.style.transform = `translateX(-${this.totalItems * 100}%)`;
                void this.carouselInner.offsetWidth; // 强制重绘
                requestAnimationFrame(() => {
                    this.carouselInner.style.transition = 'transform 0.5s ease-in-out';
                    this.carouselInner.style.transform = `translateX(-${this.currentIndex * 100}%)`;
                });
            } else if (index >= this.totalItems) {
                this.currentIndex = 0;
                this.carouselInner.style.transition = 'transform 0.5s ease-in-out';
                this.carouselInner.style.transform = `translateX(-${this.totalItems * 100}%)`;
                void this.carouselInner.offsetWidth; // 强制重绘
                requestAnimationFrame(() => {
                    this.carouselInner.style.transition = 'none';
                    this.carouselInner.style.transform = `translateX(0%)`;
                    void this.carouselInner.offsetWidth; // 强制重绘
                    this.carouselInner.style.transition = 'transform 0.5s ease-in-out';
                });
            } else {
                this.currentIndex = index;
                const offset = -this.currentIndex * 100;
                this.carouselInner.style.transition = 'transform 0.5s ease-in-out';
                requestAnimationFrame(() => {
                    this.carouselInner.style.transform = `translateX(${offset}%)`;
                });
            }
        }

        // 切换到下一张图片
        nextSlide() {
            this.showSlide(this.currentIndex + 1);
        }

        // 切换到上一张图片
        prevSlide() {
            this.showSlide(this.currentIndex - 1);
        }

        // 绑定事件
        bindEvents() {
            this.prevButton.addEventListener('click', () => this.prevSlide());
            this.nextButton.addEventListener('click', () => this.nextSlide());
        }

        // 启动自动播放
        startAutoPlay() {
            setInterval(() => this.nextSlide(), this.config.autoPlayInterval);
        }
    }

    // 使用示例
    const carousel1 = new Carousel(document.getElementById('carousel1'), {
        imageNames: ['img_1.png', 'img_2.png', 'img_3.png'], // 图片名称数组
        imageBasePath: 'images_01', // 图片基础路径
        autoPlayInterval: 3000, // 自动播放间隔
        transitionType: 'slide', // 切换方式：slide 或 fade
    });
</script>
</body>
</html>